package com.atguigu.mall.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.atguigu.common.constant.ProductConstant;
import com.atguigu.common.page.PageFactory;
import com.atguigu.common.to.SkuHasStockVO;
import com.atguigu.common.to.SkuReductionTO;
import com.atguigu.common.to.SpuBoundsTO;
import com.atguigu.common.to.es.SkuEsModel;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.R;
import com.atguigu.mall.product.dao.SpuInfoDao;
import com.atguigu.mall.product.dao.SpuInfoDescDao;
import com.atguigu.mall.product.entity.*;
import com.atguigu.mall.product.feign.CouponFeignService;
import com.atguigu.mall.product.feign.ElasticsearchFeignService;
import com.atguigu.mall.product.feign.WareFeignSevice;
import com.atguigu.mall.product.service.*;
import com.atguigu.mall.product.vo.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;


@Service("spuInfoService")
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Resource
    private CategoryService categoryService;
    @Resource
    private BrandService brandService;
    @Resource
    private SpuImagesService spuImagesService;
    @Resource
    private AttrService attrService;
    @Resource
    private SpuInfoDescDao spuInfoDescDao;
    @Resource
    private ProductAttrValueService productAttrValueService;
    @Resource
    private SkuInfoService skuInfoService;
    @Resource
    private SkuImagesService skuImagesService;
    @Resource
    private SkuSaleAttrValueService skuSaleAttrValueService;
    @Resource
    private CouponFeignService couponFeignService;
    @Resource
    private WareFeignSevice wareFeignSevice;
    @Resource
    private ElasticsearchFeignService elasticsearchFeignService;
    @Override
    public PageUtils queryPage(Map<String, Object>  params) {
        Page<SpuInfoEntity> page = PageFactory.defaultPage();
        LambdaQueryWrapper<SpuInfoEntity> wrapper = new LambdaQueryWrapper<>();
        String key  = (String) params.get("key");
        Boolean isKey = StrUtil.isNotBlank(key);
        wrapper.like(isKey,SpuInfoEntity::getSpuName,key)
                .or().eq(isKey,SpuInfoEntity::getId,key);
        String catelogIdStr  = (String) params.get("catelogId");
        if (StrUtil.isNotBlank(catelogIdStr)&&!catelogIdStr.equals("0")){
            Long catelogId = Long.parseLong(catelogIdStr);
            wrapper.eq(SpuInfoEntity::getCatalogId,catelogId);
        }
        String brandIdStr  = (String) params.get("brandId");
        if (StrUtil.isNotBlank(brandIdStr) && !brandIdStr.equals("0")){
            Long brandId = Long.parseLong(brandIdStr);
            wrapper.eq(SpuInfoEntity::getBrandId,brandId);
        }
        String statusStr  = (String) params.get("status");
        if (StrUtil.isNotBlank(statusStr)){
            Integer status = Integer.parseInt(statusStr);
            wrapper.eq(SpuInfoEntity::getPublishStatus,status);
        }
        this.page(page, wrapper);
        List<SpuInfoEntity> records = page.getRecords();
        if (CollUtil.isNotEmpty(records)){
            records.forEach(item->{
                Long catalogId = item.getCatalogId();
                Long brandId = item.getBrandId();
                CategoryEntity categoryEntity = categoryService.getById(catalogId);
                BrandEntity brand = brandService.getById(brandId);
                item.setBrandName(brand.getName());
                item.setCatalogName(categoryEntity.getName());
            });
        }
        return new PageUtils(page);
    }

    /**
     * SPU，Standard Product Unit 标准化产品单元，是商品信息聚合的最小单位，是一组可复用、易检索的标准化信息的集合，
     *      该集合描述了商品的特性。其属性值、特性相同的商品都可以称为一个SPU。
     * SPU：是用来定位的，京东前台无法看到单品的SPU是多少，
     *      想查看只能去店铺后台查看，淘宝则可以在前台链接中查看搭配商品ID，例如下图是天猫一款产品的链接，圈中的是商品ID
     * @param spuInfo
     */
    @Override
    public void saveSpuSaveVo(SpuSaveVo spuInfo) {
        /**
         * 1.保存spu 基本信息 pms_sku_info
         */
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtil.copyProperties(spuInfo,spuInfoEntity);
        this.saveBaseSpuInfo(spuInfoEntity);
        /**
         * 2.保存spu图片 描述 pms_spu_info_desc
         */
        Long spuId = spuInfoEntity.getId();
        List<String> decripts = spuInfo.getDecript();
        SpuInfoDescEntity spuDesc =SpuInfoDescEntity.builder().spuId(spuId)
                        .decript(StrUtil.join(",",decripts)).build();
        spuInfoDescDao.insert(spuDesc);
        /**
         * 3.保存spu 图片集 pms_spu_images
         */
        List<String> images = spuInfo.getImages();
        spuImagesService.saveSpuImages(images,spuId);
        /**
         * 4.保存spu 规格参数 pms_product_attr_value
         */
        List<BaseAttrs> baseAttrs = spuInfo.getBaseAttrs();
        if (CollUtil.isNotEmpty(baseAttrs)){
            List<ProductAttrValueEntity> productAttrValueEntities = baseAttrs.stream().map(item -> {
                ProductAttrValueEntity productAttrValue = new ProductAttrValueEntity();
                int showDesc = item.getShowDesc();
                BeanUtil.copyProperties(item, productAttrValue);
                productAttrValue.setSpuId(spuId);
                productAttrValue.setQuickShow(showDesc);
                AttrEntity attrEntity = attrService.getById(item.getAttrId());
                if (ObjectUtil.isNotNull(attrEntity)){
                    String attrName = attrEntity.getAttrName();
                    productAttrValue.setAttrName(attrName);
                }
                return productAttrValue;
            }).collect(Collectors.toList());
            productAttrValueService.saveAttrBatch(productAttrValueEntities);
        }
        /**
         * 5.保存 spu 积分信息 mall_sms sms_spu_bounds
         */
        Bounds bounds = spuInfo.getBounds();
        SpuBoundsTO spuBoundsTO = new SpuBoundsTO();
        BeanUtil.copyProperties(bounds,spuBoundsTO);
        spuBoundsTO.setSpuId(spuId);
        R saveSpuBoundsResult = couponFeignService.saveSpuBounds(spuBoundsTO);
        if (saveSpuBoundsResult.isSuccess()){
            log.info("远程调用保存spu积分信息成功！");
        }else {
            log.error("远程调用保存spu积分信息失败！");
        }

        /**
         * 5.保存 spu 对应的 sku 信息
         */
        List<Skus> skus = spuInfo.getSkus();
        if (CollUtil.isNotEmpty(skus)){
            skus.forEach(sku->{
                /**
                 * 5.1  sku 基本信息 pms_sku_info
                 */
                SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                BeanUtil.copyProperties(sku,skuInfoEntity);
                List<Images> imagesList = sku.getImages();
                Optional<Images> imgOptional = imagesList.stream().filter(img -> img.getDefaultImg() == 1).findFirst();

                /**
                 * 设置默认图片
                 */
                if (imgOptional.isPresent()){
                    String imgUrl = imgOptional.get().getImgUrl();
                    skuInfoEntity.setSkuDefaultImg(imgUrl);
                }
                skuInfoEntity.setBrandId(spuInfo.getBrandId());
                skuInfoEntity.setCatalogId(spuInfo.getCatalogId());
                skuInfoEntity.setSaleCount(0L);
                skuInfoEntity.setSpuId(spuId);
                skuInfoService.saveSkuInfo(skuInfoEntity);

                Long skuId = skuInfoEntity.getSkuId();
                /**
                 * 5.2 sku 图片信息 pms_sku_images
                 */
                if (CollUtil.isNotEmpty(imagesList)){
                    List<SkuImagesEntity> skuImagesList = imagesList.stream()
                            .filter(item->StrUtil.isNotBlank(item.getImgUrl()))
                            .map(img -> {

                        SkuImagesEntity imagesEntity = new SkuImagesEntity();
                        imagesEntity.setSkuId(skuId);
                        imagesEntity.setImgUrl(img.getImgUrl());
                        imagesEntity.setDefaultImg(img.getDefaultImg());
                        return imagesEntity;
                    }).collect(Collectors.toList());
                    if (CollUtil.isNotEmpty(skuImagesList)){
                     skuImagesService.saveBatch(skuImagesList);
                    }
                }
                /**
                 * 5.3 sku 销售属性 pms_sku_sale_attr_value
                 */
                List<Attr> attrs = sku.getAttr();
                if (CollUtil.isNotEmpty(attrs)){
                    List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attrs.stream().map(attr -> {
                        SkuSaleAttrValueEntity attrValue = new SkuSaleAttrValueEntity();
                        BeanUtil.copyProperties(attr, attrValue);
                        attrValue.setSkuId(skuId);
                        return attrValue;
                    }).collect(Collectors.toList());
                    skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);
                }

                /**
                 * 5.4 sku 优惠信息 mall_sms
                 *  mall_sms ：
                 *    sms_sku_ladder  sku 打折表
                 *    sms_sku_full_reduction 满减表
                 *    sms_member_price 会员价格表
                 */
                SkuReductionTO skuReductionTO = new SkuReductionTO();
                BeanUtil.copyProperties(sku,skuReductionTO);
                skuReductionTO.setSkuId(skuId);
                boolean Isprice = skuReductionTO.getFullPrice().compareTo(BigDecimal.ZERO  )==1;
                /**
                 * 满减信息 判断
                 */
                if (skuReductionTO.getFullCount() > 0  || Isprice ) {
                    R r = couponFeignService.saveSkuReduction(skuReductionTO);
                    if (r.isSuccess()){
                        log.info("远程调用保存sku优惠信息成功！");
                    }else {
                        log.error("远程调用保存sku优惠信息失败！");
                    }
                }
            });
        }
    }





    @Override
    public void saveBaseSpuInfo(SpuInfoEntity spuInfoEntity) {
        this.baseMapper.insert(spuInfoEntity);
    }

    @Override
    public void upSpu(Long spuId) {
        /**
         * 1.根据spu id 查询出所有 sku 商品
         */
        List<SkuInfoEntity> skuList = skuInfoService.getSkuBySkuId(spuId);
        List<Long> skuIdList = skuList.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        /**
         * 2.查出 spu 所有规格属性
         */
        List<ProductAttrValueEntity> productAttrValueEntities = productAttrValueService.queryBySpuId(spuId);
        List<Long> attrId = productAttrValueEntities.stream()
                .map(ProductAttrValueEntity::getAttrId)
                .distinct().collect(Collectors.toList());
        /**
         * 并查出属性是否可以用于被检索
         */
        List<AttrEntity> attrEntities = attrService.listByIds(attrId);
        /**
         * 过滤出需要被检索的属性id
         */
        List<Long> searchAttrIds = attrEntities.stream()
                .filter(attr -> attr.getSearchType().equals(1))
                .map(AttrEntity::getAttrId)
                .collect(Collectors.toList());
        List<ProductAttrValueEntity> searchProductAttrList = productAttrValueEntities.stream().filter(item -> searchAttrIds.contains(item.getAttrId())).collect(Collectors.toList());

        /**
         * 转换成最终用于检索的es attr
         */
        List<SkuEsModel.Attrs> attrs = searchProductAttrList.stream().map(item -> {
            SkuEsModel.Attrs attr = new SkuEsModel.Attrs();
            BeanUtil.copyProperties(item, attr);
            return attr;
        }).collect(Collectors.toList());

        /**
         * 查询是否有库存
         */
        List<SkuHasStockVO> skusHasStock = wareFeignSevice.getSkusHasStock(skuIdList);
        Map<Long, Boolean> skuHasStockMap = skusHasStock.stream().collect(Collectors.toMap(SkuHasStockVO::getSkuId, SkuHasStockVO::getHasStock));
        List<SkuEsModel> skuInfoList = skuList.stream().map(item -> {
            SkuEsModel skuEsModel = new SkuEsModel();
            BeanUtil.copyProperties(item, skuEsModel);
            skuEsModel.setSkuPrice(item.getPrice());
            skuEsModel.setSkuImg(item.getSkuDefaultImg());
            //TODO 1.发送远程调用是否有库存
            Boolean isStock = null;
            try {
                isStock = skuHasStockMap.get(item.getSkuId());
                if (ObjectUtil.isNull(isStock)){
                    isStock = false;
                }
            } catch (Exception e) {
                log.error("库存服务查询异常：{}",e);
                isStock = true;
            }
            skuEsModel.setHasStock(isStock);
            //TODO 2.热度评分 0
            BrandEntity brand = brandService.getById(item.getBrandId());
            CategoryEntity category = categoryService.getById(item.getCatalogId());
            skuEsModel.setBrandName(brand.getName());
            skuEsModel.setBrandImg(brand.getLogo());
            skuEsModel.setCatalogName(category.getName());
            /**
             * 查出所有可以被检索的 规格属性
             */
            skuEsModel.setAttrs(attrs);

            return skuEsModel;
        }).collect(Collectors.toList());
        R r = elasticsearchFeignService.productStatusUp(skuInfoList);
        Integer code = r.getCode();
        if (code.equals(0)){
            //TODO 上架成功
            this.updateStatus(spuId, ProductConstant.ProductStatusEnum.SPU_UP.getCode());
        }else {
            //TODO 接口幂等性，重试问题
        }
    }

    @Override
    public void updateStatus(Long spuId, Integer code) {
        SpuInfoEntity entity = new SpuInfoEntity();
        entity.setId(spuId);
        entity.setPublishStatus(code);
        this.baseMapper.updateById(entity);
    }


}